﻿using OSGeo.OSR;
using RemoteSensingImageDirectServer.Untils.Extensions;
using System.Collections.Concurrent;

namespace RemoteSensingImageDirectServer.Untils.Pool
{
    public class OsrTransformPool
    {
        /// <summary>
        /// 私有静态锁对象，减少锁的范围
        /// </summary>
        private static object syncRoot = new object();

        /// <summary>
        /// 私有静态变量引用自身实例
        /// </summary>
        private static volatile OsrTransformPool instance = null;

        /// <summary>
        /// 公有静态方法，提供一个全局访问点
        /// </summary>
        /// <returns></returns>
        public static OsrTransformPool Instance()
        {
            // 当instance为null时，才进行加锁处理
            if (instance == null)
            {
                // 双重检查锁定，提高性能
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new OsrTransformPool();
                    }
                }
            }
            return instance;
        }


        // 私有构造函数，防止外部直接创建实例
        private OsrTransformPool()
        {
            OtherSRDict = new ConcurrentDictionary<int, SpatialReference>();

            SRWGS84 = GetSRFromEPSG(4326);
            SRGCS2000 = GetSRFromEPSG(4490);
            SRWebMercator = GetSRFromEPSG(3857);

            TransformMercatorToWGS1984 = new CoordinateTransformation(SRWebMercator, SRWGS84);
            TransformWGS1984ToMercator = new CoordinateTransformation(SRWGS84, SRWebMercator);

            EPSGDict = new ConcurrentDictionary<string, int>();
            EPSGDict.TryAdd("0", 0);
            EPSGDict.TryAdd("c", 4326);
            EPSGDict.TryAdd("w", 3857);
            EPSGDict.TryAdd("epsg:0", 0);
            EPSGDict.TryAdd("epsg:4326", 4326);
            EPSGDict.TryAdd("epsg:3857", 3857);
            EPSGDict.TryAdd("epsg:102025", 102025);

            for (var i = 32601; i <= 32660; i++)
            {
                EPSGDict.TryAdd($"epsg:{i}", i);
            }

            for (var i = 4490; i <= 4554; i++)
            {
                EPSGDict.TryAdd($"epsg:{i}", i);
            }
        }

        #region gdal相关常量存储位置


        /// <summary>
        /// WGS1984坐标系参数
        /// </summary>
        public readonly SpatialReference SRWGS84;

        /// <summary>
        /// CGCS2000坐标系参数
        /// </summary>
        public readonly SpatialReference SRGCS2000;

        /// <summary>
        /// WebMercator坐标系参数
        /// </summary>
        public readonly SpatialReference SRWebMercator;

        /// <summary>
        /// 从WebMercator投影转到WGS1984坐标系的方法
        /// </summary>
        public readonly CoordinateTransformation TransformMercatorToWGS1984;

        /// <summary>
        /// 从WGS1984坐标系转到WebMercator投影的方法
        /// </summary>
        public readonly CoordinateTransformation TransformWGS1984ToMercator;

        /// <summary>
        /// 扩展投影(发布用扩展，读取用)
        /// </summary>
        public readonly ConcurrentDictionary<int, SpatialReference> OtherSRDict;

        public SpatialReference GetSRFromEPSG(int epsg)
        {
            lock (syncRoot)
            {
                if (OtherSRDict.TryGetValue(epsg, out var spatialReference))
                {
                    return spatialReference;
                }
                else
                {
                    SpatialReference pSpatialReference = new SpatialReference("");
                    pSpatialReference.ImportFromEPSG(epsg);
                    OtherSRDict.TryAdd(epsg, pSpatialReference);
                    return OtherSRDict[epsg];
                }
            }
        }

        /// <summary>
        /// 请求的投影参数注册字典
        /// </summary>
        private readonly ConcurrentDictionary<string, int> EPSGDict;

        public bool ContainsEPSG(string srs) 
        {
            return EPSGDict.ContainsKey(srs.ToLower());
        }

        public int GetEPSGFromSrs(string srs)
        {
            return EPSGDict[srs.ToLower()];
        }

        /// <summary>
        /// 请求的投影参数的key
        /// </summary>
        public string[] EPSGKeys { get { return EPSGDict.Keys.ToArray(); } }
        #endregion
    }
}
